home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-30 | 10.3 KB | 409 lines | [TEXT/CWIE] |
- /*
- LMouser is © 1996 Boxes Objects Links Design Pty Ltd. All Rights Reserved.
- You use this software at your own risk, etc. Permission is given to Timothy C.
- Delaney to use LMouser. Permission is given for all others to use LMouser if
- acknowledgement of this copyright is given in publically-released software.
- Acknowledgement should consist of a statement equivalent to "Sections of this
- program are © Boxes Objects Links Design Pty Ltd", visible in an "About..." box
- or splash screen.
- */
-
- /*
- LMouser 2.2
-
- Release data: 31/5/96
-
- LMouser is a mix-in class (like LListener) for using the MouseEnter(), MouseLeave()
- and MouseWithin() methods of an LPane.
-
- Revision History:
-
- 2.2
-
- Discovered that LView::FindDeepSubMouserContaining() would return an invisible
- pane, preventing an LMouser behind it from receiving any events. I found this
- one all by myself... A new function LMouser::FindVisibleDeepSubPaneContaining()
- is now part of the package.
-
- 2.1
-
- Fixed a logical error which got introduced somewhere after 1.0: only LMousers in
- the active window would respond. This has been removed. Thanks to Daniel Sears
- for pointing this out.
-
- 2.0
-
- Fixed a bug which could result in a crash if the mouse is inside a mouser when
- that mouser is destroyed. This might account for a number of crashes I was
- getting in my other code. Thanks Bill Hubauer.
-
- Made LMouseDispatcher internal to LMouser.cp (and hence invisible to the rest of
- the world). LMouseDispatcher now inherits from LPeriodical and installs an
- instance of itself as a repeater with StartRepeating(). As a side effect,
- LMousers are now dealt with *after* events are dispatched (when AdjustCursor()
- in the application class was being overridden they were being dealt with
- beforehand). The application class now no longer (and indeed cannot) inherit
- from LMouseDispatcher.
-
- 1.1
-
- Split LMouser into two classes: LMouser and LMouseDispatcher. The application
- class is to inherit from LMouseDispatcher. Used, but never released.
-
- 1.0
-
- First release.
- */
-
- #include <Windows.h>
-
- #include <LPane.h>
- #include "LMouser.h"
- #include <LPeriodical.h>
- #include <LWindow.h>
- #include <LArray.h>
-
- #pragma RTTI on
-
- LMouser *LMouser::sLastMouser = NULL;
- LPane *LMouser::sLastPane = NULL,
- *LMouser::sCurrentPane = NULL;
-
- class LMouseDispatcher : private LMouser, public LPeriodical
- {
- public:
-
- LMouseDispatcher (void );
- virtual ~LMouseDispatcher (void );
-
- virtual void SpendTime (const EventRecord &inMacEvent );
-
- virtual LMouser * GetSuperMouser (void );
-
- static LMouseDispatcher * GetMouseDispatcher (void );
-
- void AddMouser (LMouser *theMouser );
-
- void RemoveMouser (LMouser *theMouser );
-
- private:
-
- static LMouseDispatcher sMouseDispatcher;
- static LArray sMousers;
-
- virtual LMouser * FindDeepSubMouserContaining (const EventRecord &inMacEvent );
- virtual LMouser * FindShallowSubMouserContaining (const EventRecord &inMacEvent );
-
- };
-
- LMouseDispatcher LMouseDispatcher::sMouseDispatcher;
- LArray LMouseDispatcher::sMousers(sizeof(LMouser *));
-
- LMouser::LMouser (void )
- {
- mSuperMouser = NULL;
-
- if (this != LMouseDispatcher::GetMouseDispatcher())
- {
- LMouseDispatcher::GetMouseDispatcher()->AddMouser(this);
- }
- }
-
- LMouser::~LMouser (void )
- {
- if (this == sLastMouser)
- {
- sLastMouser = NULL;
- sLastPane = NULL;
- }
-
- if (this != LMouseDispatcher::GetMouseDispatcher())
- {
- LMouseDispatcher::GetMouseDispatcher()->RemoveMouser(this);
- }
- }
-
- /*
- LPane::FindDeepSubPaneContaining() will return an invisible pane: not what we want. So
- we will create our own function which returns the deepest *visible* subpane.
- */
-
- LPane * LMouser::FindVisibleDeepSubPaneContaining (Int32 inHorizPort,
- Int32 inVertPort,
- LPane *startPane )
- {
- LView *startView = dynamic_cast<LView *>(startPane);
-
- LPane *hitSubPane = startPane;
-
- if (startView)
- {
- LListIterator iterator(startView->GetSubPanes(), iterate_FromEnd);
- LPane *theSub;
-
- while (iterator.Previous(&theSub))
- {
- if (theSub->IsVisible() && theSub->Contains(inHorizPort, inVertPort))
- {
- hitSubPane = FindVisibleDeepSubPaneContaining(inHorizPort, inVertPort, theSub);
- break;
- }
- }
- }
-
- return hitSubPane;
- }
-
- /*
- LMouser::FindDeepSubMouserContaining() corresponds to LPane::FindDeepSubPaneContaining()
- This function takes an optional LPane * parameter. This is because not every pane is an
- LMouser - if the application (for example) is finding the deepest LMouser it can, it must
- be able to find it whether or not the window containing the mouse point is an LMouser.
- */
-
- LMouser * LMouser::FindDeepSubMouserContaining (Int32 inHorizPort,
- Int32 inVertPort,
- LPane * startPane )
- {
- LPane *tempPane = NULL;
- LMouser *mouserHit = NULL;
-
- mouserHit = NULL;
-
- if (!startPane)
- {
- startPane = dynamic_cast<LPane *>(this);
- }
-
- if (startPane)
- {
- tempPane = //startPane->FindDeepSubPaneContaining(inHorizPort, inVertPort);
- FindVisibleDeepSubPaneContaining(inHorizPort, inVertPort, startPane);
-
- if (tempPane)
- {
- startPane = tempPane;
- }
- }
-
- while (startPane && (!mouserHit || !tempPane->IsEnabled()))
- {
- mouserHit = dynamic_cast<LMouser *>(startPane);
- tempPane = startPane;
- startPane = (LPane *) startPane->GetSuperView();
- }
-
- return mouserHit;
- }
-
- /*
- LMouser::FindShallowSubMouserContaining() corresponds to LPane::FindShallowSubPaneContaining()
- This function takes an optional LPane * parameter. This is because not every pane is an
- LMouser - if the application (for example) is finding the shallowest LMouser it can, it must
- be able to find it whether or not the window containing the mouse point is an LMouser.
- */
-
- LMouser * LMouser::FindShallowSubMouserContaining (Int32 inHorizPort,
- Int32 inVertPort,
- LPane * startPane )
- {
- LMouser *mouserHit = NULL;
-
- mouserHit = NULL;
-
- if (!startPane)
- {
- startPane = dynamic_cast<LPane *>(this);
- }
-
- LPane *tempPane = NULL;
-
- while (startPane && (!mouserHit || !tempPane->IsEnabled()))
- {
- mouserHit = dynamic_cast<LMouser *>(startPane);
- tempPane = startPane;
- startPane = startPane->FindShallowSubPaneContaining(inHorizPort, inVertPort);
- }
-
- return mouserHit;
- }
-
- /*
- Rather than storing the supermouser as a field, simply go up the list of SuperViews of the
- current LMouser (LPane) until we find another LMouser or we run out. The application, even
- though it must be an LMouser, is never the SuperMouser of an LMouser.
- */
-
- LMouser * LMouser::GetSuperMouser (void )
- {
- LPane *curPane = dynamic_cast<LPane *>(this);
-
- mSuperMouser = NULL;
-
- while (curPane && !mSuperMouser)
- {
- curPane = (LPane *) curPane->GetSuperView();
- mSuperMouser = dynamic_cast<LMouser *>(curPane);
- }
-
- return mSuperMouser;
- }
-
- LPane * LMouser::GetLastPane (void )
- {
- return sLastPane;
- }
-
- LPane * LMouser::GetCurrentPane (void )
- {
- return sCurrentPane;
- }
-
- /*
- If the currently hit LMouser is different to the previous LMouser, call the MouseLeave()
- function for the LMouser (which is an LPane). Then call the MouseEnter() function for the
- new LMouser. If the mouse didn't change mousers then call the MouseWithin() function.
-
- This function does not pass unused mouse events to the SuperMouser - if a pane/mouser wants
- to do this it must be done inside the MouseLeave(), MouseEnter() and MouseWithin()
- functions. It is assumed that an LMouser will deal with all three mouse events.
- */
-
- LMouseDispatcher::LMouseDispatcher (void )
- {
- StartRepeating();
- }
-
- LMouseDispatcher::~LMouseDispatcher (void )
- {
- }
-
- LMouseDispatcher * LMouseDispatcher::GetMouseDispatcher (void )
- {
- return &sMouseDispatcher;
- }
-
- void LMouseDispatcher::AddMouser (LMouser *theMouser )
- {
- if (theMouser && sMousers.FetchIndexOf(&theMouser) == LArray::index_Bad)
- {
- sMousers.InsertItemsAt(1, LArray::index_Last, &theMouser);
- }
- }
-
- void LMouseDispatcher::RemoveMouser (LMouser *theMouser )
- {
- if (theMouser)
- {
- sMousers.Remove(&theMouser);
- }
- }
-
- void LMouseDispatcher::SpendTime (const EventRecord &inMacEvent )
- {
- sLastPane = sCurrentPane;
- sLastMouser = dynamic_cast<LMouser *>(sLastPane);
- sCurrentPane = NULL;
-
- if (sMousers.GetCount() == 0)
- {
- return;
- }
-
- Point portMouse = inMacEvent.where;
-
- LMouser *mouserHit = NULL;
-
- Boolean mouserChanged;
-
- mouserHit = FindDeepSubMouserContaining(inMacEvent);
- sCurrentPane = dynamic_cast<LPane *>(mouserHit);
- mouserChanged = sLastPane != sCurrentPane;
-
- if (sLastPane && mouserChanged)
- {
- sLastPane->MouseLeave();
- }
-
- if (sCurrentPane)
- {
- sCurrentPane->GlobalToPortPoint(portMouse);
-
- if (mouserChanged)
- {
- sCurrentPane->MouseEnter(portMouse, inMacEvent);
- }
- else
- {
- sCurrentPane->MouseWithin(portMouse, inMacEvent);
- }
- }
- }
-
- /*
- When only an event record is given it is still possible to find the deepest LMouser -
- first the correct window needs to be found, then the correct subpane can be found.
- */
-
- LMouser * LMouseDispatcher::FindDeepSubMouserContaining (const EventRecord &inMacEvent )
- {
- WindowPtr macWindowP;
- Point globalMouse = inMacEvent.where;
- LMouser *mouserHit = NULL;
-
- short thePart = ::FindWindow(globalMouse, &macWindowP);
- LWindow *theWindow = LWindow::FetchWindowObject(macWindowP);
-
- if ((theWindow != NULL) && theWindow->IsEnabled())
- {
- theWindow->GlobalToPortPoint(globalMouse);
- mouserHit = LMouser::FindDeepSubMouserContaining(globalMouse.h, globalMouse.v, theWindow);
- }
- else
- {
- mouserHit = NULL;
- }
-
- return mouserHit;
- }
-
- /*
- When only an event record is given it is still possible to find the shallowest LMouser -
- first the correct window needs to be found, then the correct subpane can be found.
- */
-
- LMouser * LMouseDispatcher::FindShallowSubMouserContaining (const EventRecord &inMacEvent )
- {
- WindowPtr macWindowP;
- Point globalMouse = inMacEvent.where;
- LMouser *mouserHit = NULL;
-
- ::FindWindow(globalMouse, &macWindowP);
-
- LWindow *theWindow = LWindow::FetchWindowObject(macWindowP);
-
- if ((theWindow != nil) && theWindow->IsEnabled())
- {
- theWindow->GlobalToPortPoint(globalMouse);
- mouserHit = LMouser::FindShallowSubMouserContaining(globalMouse.h, globalMouse.v, theWindow);
-
- if (!mouserHit)
- {
- mouserHit = dynamic_cast<LMouser *>(theWindow);
- }
- }
- else
- {
- mouserHit = NULL;
- }
-
- return mouserHit;
- }
-
- LMouser * LMouseDispatcher::GetSuperMouser (void )
- {
- return NULL;
- }
-
- #pragma RTTI reset
-